package cc.rengu.oltp.utility.util;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 金额操作工具灯
 * Created by 王成 on 2018/5/10.
 */
public class AmountUtil {
    /**
     * 加法运算
     *
     * @param amt1 金额字符串1
     * @param amt2 金额字符串2
     * @return 金额字符串1 + 金额字符串2
     */
    public static String addition(String amt1, String amt2) {
        BigDecimal bigDecimal1;
        BigDecimal bigDecimal2;
        if (null == amt1 || 0 == amt1.trim().length()) {
            bigDecimal1 = new BigDecimal(0);
        } else {
            bigDecimal1 = new BigDecimal(amt1);
        }

        if (null == amt2 || 0 == amt2.trim().length()) {
            bigDecimal2 = new BigDecimal(0);
        } else {
            bigDecimal2 = new BigDecimal(amt2);
        }
        return bigDecimal1.add(bigDecimal2).toString();
    }

    /**
     * 减法运算
     *
     * @param amt1 金额字符串1
     * @param amt2 金额字符串2
     * @return 金额字符串1 - 金额字符串2
     */
    public static String subtraction(String amt1, String amt2) {
        BigDecimal bigDecimal1;
        BigDecimal bigDecimal2;
        if (null == amt1 || 0 == amt1.trim().length()) {
            bigDecimal1 = new BigDecimal(0);
        } else {
            bigDecimal1 = new BigDecimal(amt1);
        }

        if (null == amt2 || 0 == amt2.trim().length()) {
            bigDecimal2 = new BigDecimal(0);
        } else {
            bigDecimal2 = new BigDecimal(amt2);
        }
        return bigDecimal1.subtract(bigDecimal2).toString();
    }

    /**
     * 乘法运算
     *
     * @param amt1 金额字符串1
     * @param amt2 金额字符串2
     * @return 金额字符串1 * 金额字符串2
     */
    public static String multiplication(String amt1, String amt2) {
        BigDecimal bigDecimal1;
        BigDecimal bigDecimal2;
        if (null == amt1 || 0 == amt1.trim().length()) {
            bigDecimal1 = new BigDecimal(0);
        } else {
            bigDecimal1 = new BigDecimal(amt1);
        }

        if (null == amt2 || 0 == amt2.trim().length()) {
            bigDecimal2 = new BigDecimal(0);
        } else {
            bigDecimal2 = new BigDecimal(amt2);
        }
        return bigDecimal1.multiply(bigDecimal2).toString();
    }

    /**
     * 乘法运算
     *
     * @param amt1  金额字符串1
     * @param amt2  金额字符串2
     * @param scale 小数点精度
     * @return 金额字符串1 * 金额字符串2
     */
    public static String multiplication(String amt1, String amt2, int scale) {
        BigDecimal bigDecimal1;
        BigDecimal bigDecimal2;
        if (null == amt1 || 0 == amt1.trim().length()) {
            bigDecimal1 = new BigDecimal(0);
        } else {
            bigDecimal1 = new BigDecimal(amt1);
        }

        if (null == amt2 || 0 == amt2.trim().length()) {
            bigDecimal2 = new BigDecimal(0);
        } else {
            bigDecimal2 = new BigDecimal(amt2);
        }
        return bigDecimal1.multiply(bigDecimal2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
    }

    /**
     * 除法运算
     *
     * @param amt1 金额字符串1
     * @param amt2 金额字符串2
     * @return 金额字符串1 / 金额字符串2
     */
    public static String division(String amt1, String amt2) {
        BigDecimal bigDecimal1;
        BigDecimal bigDecimal2;
        if (null == amt1 || 0 == amt1.trim().length()) {
            bigDecimal1 = new BigDecimal(0);
        } else {
            bigDecimal1 = new BigDecimal(amt1);
        }

        if (null == amt2 || 0 == amt2.trim().length()) {
            bigDecimal2 = new BigDecimal(0);
        } else {
            bigDecimal2 = new BigDecimal(amt2);
        }

        if (0 == bigDecimal2.compareTo(BigDecimal.ZERO)) {
            return "0";
        } else {
            return bigDecimal1.divide(bigDecimal2, 2, RoundingMode.HALF_UP).toString();
        }
    }

    /**
     * 除法运算
     *
     * @param amt1  金额字符串1
     * @param amt2  金额字符串2
     * @param scale 小数点精度
     * @return 金额字符串1 / 金额字符串2
     */
    public static String division(String amt1, String amt2, int scale) {
        BigDecimal bigDecimal1;
        BigDecimal bigDecimal2;
        if (null == amt1 || 0 == amt1.trim().length()) {
            bigDecimal1 = new BigDecimal(0);
        } else {
            bigDecimal1 = new BigDecimal(amt1);
        }

        if (null == amt2 || 0 == amt2.trim().length()) {
            bigDecimal2 = new BigDecimal(0);
        } else {
            bigDecimal2 = new BigDecimal(amt2);
        }

        if (0 == bigDecimal2.compareTo(BigDecimal.ZERO)) {
            return "0";
        } else {
            return bigDecimal1.divide(bigDecimal2, scale, RoundingMode.HALF_UP).toString();
        }
    }

    /**
     * 四舍五入处理
     *
     * @param amt1  需要四舍五入的金额
     * @param scale 小数点精度
     * @return 四舍五入结果
     */
    public static String rounding(String amt1, int scale) {
        BigDecimal bigDecimal1;
        if (null == amt1 || 0 == amt1.trim().length()) {
            bigDecimal1 = new BigDecimal(0);
        } else {
            bigDecimal1 = new BigDecimal(amt1);
        }
        BigDecimal one = new BigDecimal("1");
        return bigDecimal1.divide(one, scale, BigDecimal.ROUND_HALF_UP).toString();
    }

    /**
     * 比较金额大小
     *
     * @param amt1 金额字符串1
     * @param amt2 金额字符串2
     * @return amt1>amt2 返回1，amt1=amt2 返回0，amt1<amt2 返回-1
     */
    public static int compare(String amt1, String amt2) {
        BigDecimal bigDecimal1;
        BigDecimal bigDecimal2;
        if (null == amt1 || 0 == amt1.trim().length()) {
            bigDecimal1 = new BigDecimal(0);
        } else {
            bigDecimal1 = new BigDecimal(amt1);
        }

        if (null == amt2 || 0 == amt2.trim().length()) {
            bigDecimal2 = new BigDecimal(0);
        } else {
            bigDecimal2 = new BigDecimal(amt2);
        }
        return bigDecimal1.compareTo(bigDecimal2);
    }

    /**
     * 元转分
     *
     * @param amount 以元为单位的金额
     * @return 以分为单位的金额
     */
    public static String changeY2F(String amount) {
        BigDecimal bigDecimal;
        if (null == amount || 0 == amount.trim().length()) {
            bigDecimal = new BigDecimal(0);
        } else {
            bigDecimal = new BigDecimal(amount);
        }
        bigDecimal = bigDecimal.multiply(new BigDecimal(100));
        return bigDecimal.toBigInteger().toString();
    }

    /**
     * 分转元
     *
     * @param amount 以分为单位的金额
     * @return 以元为单位的金额
     */
    public static String changeF2Y(String amount) {
        BigDecimal bigDecimal;
        if (null == amount || 0 == amount.trim().length()) {
            bigDecimal = new BigDecimal(0);
        } else {
            bigDecimal = new BigDecimal(amount);
        }
        bigDecimal = bigDecimal.divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN);
        return bigDecimal.toString();
    }

    /**
     * 明确金额不能为0,不能为负的金额检查，检查通过返回格式化后的金额
     * <p>
     * 例如保留精度2位则返回带两位小数的标准格式即使为.00
     *
     * @param amt   待检查金额
     * @param scale 需要检查金额的精度，上送的金额必须不大于该精度，返回时使用该精度返回格式化金额
     * @return 检查通过后格式化的金额带 {@param scale} 小数位的金额，即使小数部分金额为0
     * @throws Exception 检查不通过抛出异常
     */
    public static String checkAmt(String amt, int scale) throws Exception {
        return checkAmt(amt, scale, true, true);
    }

    /**
     * 明确金额不能为0的金额检查，检查通过返回格式化后的金额
     * <p>
     * 例如保留精度2位则返回带两位小数的标准格式即使为.00
     *
     * @param amt           待检查金额
     * @param scale         需要检查金额的精度，上送的金额必须不大于该精度，返回时使用该精度返回格式化金额
     * @param allowNegative 是否允许金额为负数 true表示允许，false表示不允许
     * @return 检查通过后格式化的金额带 {@param scale} 小数位的金额，即使小数部分金额为0
     * @throws Exception 检查不通过抛出异常
     */
    public static String checkAmt(String amt, int scale, boolean allowNegative) throws Exception {
        return checkAmt(amt, scale, allowNegative, true);
    }

    /**
     * 检查金额，检查通过返回格式化后的金额
     * <p>
     * 例如保留精度2位则返回带两位小数的标准格式即使为.00
     *
     * @param amt           待检查金额
     * @param scale         需要检查金额的精度，上送的金额必须不大于该精度，返回时使用该精度返回格式化金额
     * @param allowNegative 是否允许金额为负数 true表示允许，false表示不允许
     * @param allowZero     是否允许金额为0 true表示允许，false表示不允许
     * @return 检查通过后格式化的金额带 {@param scale} 小数位的金额，即使小数部分金额为0
     * @throws Exception 检查不通过抛出异常
     */
    public static String checkAmt(String amt, int scale, boolean allowNegative, boolean allowZero) throws Exception {
        if (allowZero) {
            if (StringUtil.isEmptyOrNull(amt)) {
                amt = "0";
            }
        } else {
            if (StringUtil.isEmptyOrNull(amt)) {
                throw new Exception("金额[" + amt + "]非法");
            }
        }
        if (scale <= 0) {
            throw new Exception("精度[" + scale + "]非法");
        }
        BigDecimal bigDecimal;
        try {
            bigDecimal = new BigDecimal(amt);
        } catch (NumberFormatException e) {
            throw new Exception("金额[" + amt + "]非法");
        }
        if (!allowZero) {
            if (0 == bigDecimal.compareTo(BigDecimal.ZERO)) {
                throw new Exception("金额[" + amt + "]不允许为0");
            }
        }
        if (bigDecimal.scale() > scale) {
            throw new Exception("金额[" + amt + "]精度大于" + scale);
        }
        bigDecimal = bigDecimal.setScale(scale);
        String amtNew = bigDecimal.toString();
        if (!allowNegative) {
            if (amtNew.startsWith("-")) {
                throw new Exception("金额[" + amt + "]不允许为负数");
            }
        }
        return amtNew;
    }
}
